#!/usr/bin/env python3
"""
结果报告生成器

生成详细的实验报告，包含方法、处理逻辑、结果解释和推论
"""

from typing import Dict, List, Optional, Any
from pathlib import Path
from datetime import datetime
import json

import sys
sys.path.append(str(Path(__file__).parent.parent.parent))
from utils.logger import get_logger


class ReportGenerator:
    """报告生成器"""
    
    def __init__(self, output_dir: str = "results"):
        """
        初始化报告生成器
        
        Args:
            output_dir: 输出目录
        """
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)
        self.logger = get_logger("ReportGenerator")
    
    def generate_experiment_report(self,
                                   experiment_name: str,
                                   method_description: str,
                                   processing_logic: str,
                                   results: Dict[str, Any],
                                   metrics: Dict[str, float],
                                   interpretations: List[str],
                                   conclusions: List[str],
                                   figures: Optional[List[str]] = None,
                                   config: Optional[Dict[str, Any]] = None) -> str:
        """
        生成实验报告
        
        Args:
            experiment_name: 实验名称
            method_description: 方法描述
            processing_logic: 处理逻辑说明
            results: 结果字典
            metrics: 指标字典
            interpretations: 结果解释列表
            conclusions: 结论列表
            figures: 图表文件路径列表（可选）
            config: 配置信息（可选）
            
        Returns:
            报告文件路径
        """
        # 创建实验目录
        exp_dir = self.output_dir / experiment_name
        exp_dir.mkdir(parents=True, exist_ok=True)
        
        # 生成报告内容
        report_content = self._format_report(
            experiment_name=experiment_name,
            method_description=method_description,
            processing_logic=processing_logic,
            results=results,
            metrics=metrics,
            interpretations=interpretations,
            conclusions=conclusions,
            figures=figures,
            config=config
        )
        
        # 保存报告
        report_path = exp_dir / f"{experiment_name}_report.md"
        with open(report_path, 'w', encoding='utf-8') as f:
            f.write(report_content)
        
        # 保存JSON格式的结果
        json_path = exp_dir / f"{experiment_name}_results.json"
        # 处理Config对象，转换为字典
        if hasattr(config, 'to_dict'):
            config_dict = config.to_dict()
        elif isinstance(config, dict):
            config_dict = config
        else:
            config_dict = {}
        
        with open(json_path, 'w', encoding='utf-8') as f:
            json.dump({
                'experiment_name': experiment_name,
                'timestamp': datetime.now().isoformat(),
                'metrics': metrics,
                'results': results,
                'config': config_dict,
                'figures': figures or []
            }, f, indent=2, ensure_ascii=False)
        
        self.logger.info(f"实验报告已生成: {report_path}")
        return str(report_path)
    
    def _format_report(self,
                      experiment_name: str,
                      method_description: str,
                      processing_logic: str,
                      results: Dict[str, Any],
                      metrics: Dict[str, float],
                      interpretations: List[str],
                      conclusions: List[str],
                      figures: Optional[List[str]] = None,
                      config: Optional[Dict[str, Any]] = None) -> str:
        """格式化报告内容"""
        
        report_lines = [
            f"# {experiment_name} 实验报告",
            "",
            f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            "",
            "---",
            "",
            "## 1. 方法描述",
            "",
            method_description,
            "",
            "---",
            "",
            "## 2. 处理逻辑",
            "",
            processing_logic,
            "",
            "---",
            "",
            "## 3. 实验结果",
            "",
            "### 3.1 评估指标",
            "",
            "| 指标 | 数值 |",
            "|------|------|"
        ]
        
        # 添加指标表格
        for metric_name, value in metrics.items():
            if isinstance(value, float):
                report_lines.append(f"| {metric_name} | {value:.4f} |")
            else:
                report_lines.append(f"| {metric_name} | {value} |")
        
        report_lines.extend([
            "",
            "### 3.2 详细结果",
            "",
            "```json"
        ])
        
        # 添加详细结果（JSON格式）
        report_lines.append(json.dumps(results, indent=2, ensure_ascii=False))
        report_lines.extend([
            "```",
            "",
            "---",
            "",
            "## 4. 结果解释",
            ""
        ])
        
        # 添加解释
        for i, interpretation in enumerate(interpretations, 1):
            report_lines.append(f"{i}. {interpretation}")
            report_lines.append("")
        
        report_lines.extend([
            "---",
            "",
            "## 5. 结论与推论",
            ""
        ])
        
        # 添加结论
        for i, conclusion in enumerate(conclusions, 1):
            report_lines.append(f"{i}. {conclusion}")
            report_lines.append("")
        
        # 添加图表
        if figures:
            report_lines.extend([
                "---",
                "",
                "## 6. 可视化结果",
                ""
            ])
            for i, figure_path in enumerate(figures, 1):
                figure_name = Path(figure_path).name
                report_lines.append(f"### 图 {i}: {figure_name}")
                report_lines.append("")
                report_lines.append(f"![{figure_name}]({figure_path})")
                report_lines.append("")
        
        # 添加配置信息
        if config:
            report_lines.extend([
                "---",
                "",
                "## 7. 实验配置",
                "",
                "```json"
            ])
            # 处理Config对象，转换为字典
            if hasattr(config, 'to_dict'):
                config_dict = config.to_dict()
            elif isinstance(config, dict):
                config_dict = config
            else:
                config_dict = {}
            report_lines.append(json.dumps(config_dict, indent=2, ensure_ascii=False))
            report_lines.extend([
                "```",
                ""
            ])
        
        return "\n".join(report_lines)
    
    def generate_comparison_report(self,
                                  comparison_name: str,
                                  methods: List[str],
                                  results: Dict[str, Dict[str, float]],
                                  analysis: str,
                                  conclusions: List[str],
                                  figures: Optional[List[str]] = None) -> str:
        """
        生成对比实验报告
        
        Args:
            comparison_name: 对比实验名称
            methods: 方法列表
            results: 结果字典 {method: {metric: value}}
            analysis: 对比分析说明
            conclusions: 结论列表
            figures: 图表文件路径列表（可选）
            
        Returns:
            报告文件路径
        """
        exp_dir = self.output_dir / "comparison"
        exp_dir.mkdir(parents=True, exist_ok=True)
        
        # 生成报告内容
        report_lines = [
            f"# {comparison_name} 对比实验报告",
            "",
            f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            "",
            "---",
            "",
            "## 1. 对比方法",
            ""
        ]
        
        for i, method in enumerate(methods, 1):
            report_lines.append(f"{i}. {method}")
        
        report_lines.extend([
            "",
            "---",
            "",
            "## 2. 对比结果",
            "",
            "| 方法 | " + " | ".join(list(results[methods[0]].keys())) + " |",
            "|------|" + "|".join(["------"] * len(results[methods[0]])) + "|"
        ])
        
        for method in methods:
            values = [str(results[method].get(metric, "N/A")) for metric in results[methods[0]].keys()]
            report_lines.append(f"| {method} | " + " | ".join(values) + " |")
        
        report_lines.extend([
            "",
            "---",
            "",
            "## 3. 对比分析",
            "",
            analysis,
            "",
            "---",
            "",
            "## 4. 结论",
            ""
        ])
        
        for i, conclusion in enumerate(conclusions, 1):
            report_lines.append(f"{i}. {conclusion}")
            report_lines.append("")
        
        if figures:
            report_lines.extend([
                "---",
                "",
                "## 5. 可视化结果",
                ""
            ])
            for i, figure_path in enumerate(figures, 1):
                figure_name = Path(figure_path).name
                report_lines.append(f"### 图 {i}: {figure_name}")
                report_lines.append("")
                report_lines.append(f"![{figure_name}]({figure_path})")
                report_lines.append("")
        
        report_content = "\n".join(report_lines)
        
        # 保存报告
        report_path = exp_dir / f"{comparison_name}_comparison_report.md"
        with open(report_path, 'w', encoding='utf-8') as f:
            f.write(report_content)
        
        self.logger.info(f"对比实验报告已生成: {report_path}")
        return str(report_path)
    
    def generate_ablation_report(self,
                                ablation_name: str,
                                components: List[str],
                                results: Dict[str, Dict[str, float]],
                                analysis: str,
                                conclusions: List[str],
                                figures: Optional[List[str]] = None) -> str:
        """
        生成消融实验报告
        
        Args:
            ablation_name: 消融实验名称
            components: 组件列表
            results: 结果字典 {component: {metric: value}}
            analysis: 消融分析说明
            conclusions: 结论列表
            figures: 图表文件路径列表（可选）
            
        Returns:
            报告文件路径
        """
        exp_dir = self.output_dir / "ablation"
        exp_dir.mkdir(parents=True, exist_ok=True)
        
        # 生成报告内容（类似对比报告，但针对组件）
        report_lines = [
            f"# {ablation_name} 消融实验报告",
            "",
            f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            "",
            "---",
            "",
            "## 1. 消融组件",
            ""
        ]
        
        for i, component in enumerate(components, 1):
            report_lines.append(f"{i}. {component}")
        
        report_lines.extend([
            "",
            "---",
            "",
            "## 2. 消融结果",
            "",
            "| 组件 | " + " | ".join(list(results[components[0]].keys())) + " |",
            "|------|" + "|".join(["------"] * len(results[components[0]])) + "|"
        ])
        
        for component in components:
            values = [str(results[component].get(metric, "N/A")) for metric in results[components[0]].keys()]
            report_lines.append(f"| {component} | " + " | ".join(values) + " |")
        
        report_lines.extend([
            "",
            "---",
            "",
            "## 3. 消融分析",
            "",
            analysis,
            "",
            "---",
            "",
            "## 4. 结论",
            ""
        ])
        
        for i, conclusion in enumerate(conclusions, 1):
            report_lines.append(f"{i}. {conclusion}")
            report_lines.append("")
        
        if figures:
            report_lines.extend([
                "---",
                "",
                "## 5. 可视化结果",
                ""
            ])
            for i, figure_path in enumerate(figures, 1):
                figure_name = Path(figure_path).name
                report_lines.append(f"### 图 {i}: {figure_name}")
                report_lines.append("")
                report_lines.append(f"![{figure_name}]({figure_path})")
                report_lines.append("")
        
        report_content = "\n".join(report_lines)
        
        # 保存报告
        report_path = exp_dir / f"{ablation_name}_ablation_report.md"
        with open(report_path, 'w', encoding='utf-8') as f:
            f.write(report_content)
        
        self.logger.info(f"消融实验报告已生成: {report_path}")
        return str(report_path)
